package org.reos.ReParser;

import org.reos.ReGenConfigData.ISection;
import org.reos.ReGenConfigData.Section;
import org.reos.ReGenConfigData.SectionAttribute;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class RTGenConfigReader {
    private final static String OVERRIDE_START = "<override>";
    private final static String OVERRIDE_END = "</override>";

	private ArrayList<ISection> sections = new ArrayList<ISection>();
    private boolean override = false;

	public ArrayList<ISection> populateConfigFromFile(String pathToInputFile) {
        if (pathToInputFile == null || pathToInputFile.equals("")) {
            System.out.println("Error: Path to file is not specified");
            return null;
        }
        ArrayList<String> fileData = new ArrayList<String>();
        String baseAddr;

		try {
            File f = new File(pathToInputFile);
            baseAddr = f.getParent() + "\\";
			BufferedReader br = new BufferedReader(new FileReader(f));
			String str;
			while ((str = br.readLine()) != null) {
				fileData.add(str);
			}
			br.close();
		} catch (FileNotFoundException e) {
			System.out.println("Could not find the file: " + pathToInputFile);
			//e.printStackTrace();
            return sections;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
            return sections;
		}

        try {
            parseFileData(fileData, baseAddr);
        } catch (Exception e) {
            System.out.println("Could not parse the file: " + pathToInputFile);
            return null;
        }
        return sections;
	}

    private void parseFileData(ArrayList<String> fileData, String baseAddr) throws Exception {
		ISection currentSection = null;
		String currentSectionName;
        boolean includePossible = true;

		for (String line : fileData) {
            String str = getPureString(line);
            if (str.equals("")) {
                continue;
            }

            if (includePossible) {
                String includeFile;
                if ((includeFile = getIncludeFileName(str)) != null) {
                    System.out.println("Include file <" + includeFile + "> is about to be parsed");
                    if (populateConfigFromFile(baseAddr + includeFile) == null) {
                        throw new Exception();
                    }
                    continue;
                }
            }
            includePossible = false;

            String tempSectionName;
            if ((tempSectionName = Section.parseSectionName(str)) != null) {
                currentSection = null;
                currentSectionName = tempSectionName;
                for (ISection section : sections) {
                    if (section.getSectionName().equals(currentSectionName)) {
                        currentSection = section;
                        break;
                    }
                }
                if (currentSection == null) {
                    currentSection = Section.getInstance(currentSectionName);
                    sections.add(currentSection);
                }
            } else {
                ISection sectionToUpdate = null;
                SectionAttribute attribute = null;
                if (isOverridingStr(str)) {
                    attribute = parseOverridingStr(str);
                    sectionToUpdate = Section.getSectionWithName(attribute.getSectionName(), sections);
                    override = true;
                } else {
                    if (currentSection == null) {
                        System.out.println("Error line " + str + ": One of the supported sections expected, the line is ignored");
                        continue;
                    }
                    attribute = parseAttributeStr(str, currentSection.getSectionName());
                    sectionToUpdate = currentSection;
                    override = false;
                }
                if (sectionToUpdate.isEntryValid(attribute.getSectionName(), attribute.getKey(), attribute.getValue())) {
                    if (!sectionToUpdate.setSectionAttribute(attribute, override)) {
                        throw new Exception();
                    }
                } else {
                    System.out.println("Error in line " + str + ", the line is ignored");
                }
            }
//			System.out.println(str);
		}
	}

    private SectionAttribute parseAttributeStr(String str, String sectionName) {
        String[] tmp = str.split("=");
        return new SectionAttribute(sectionName, tmp[0].trim(), tmp[1].trim());
    }

    private boolean isOverridingStr(String str) {
        return str.split("=")[0].contains(".");
    }

    public SectionAttribute parseOverridingStr(String str) {
        String[] tmp = str.split("=");
        String value = tmp[1].trim();
        String key, sectionName;
        tmp = tmp[0].split("\\.");
        sectionName = tmp[0].replace(" ", "");
        key = tmp[1].trim();
        return new SectionAttribute(sectionName, key, value);
    }

    private String getIncludeFileName(String str) {
        if (str.startsWith("#include")) {
            int beginIndex = str.indexOf('<');
            int endIndex = str.indexOf('>');
            if (beginIndex > -1 && beginIndex < endIndex) {
                return str.substring(beginIndex + 1, endIndex);
            }
        }
        return null;
    }

    private String getPureString(String str) {
		String[] tmp = str.split("##");
		return ((tmp.length == 0) ? "" : tmp[0].trim());
	}
	
}
